/* 交叉类型：A&B 合并AB的所有属性 */
// function merge<T, U>(first: T, second: U): T & U {
//   let result = <T & U>{};

//   for (let id in first) {
//     (<any>result)[id] = (<any>first)[id];
//   }

//   for (let id in second) {
//     (<any>result)[id] = (<any>second)[id];
//   }

//   return result;
// }

// class Person {
//   constructor(public name: string) {}
// }
// interface Loggable {
//   log(): void;
// }
// class ConsoleLogger implements Loggable {
//   log() {
//     console.log(this);
//   }
// }
// var jim = merge(new Person("Jim"), new ConsoleLogger());
// var n = jim.name;
// jim.log();

/* 联合类型: A|B */
// interface Bird {
//     fly();
//     layEggs();
// }

// interface Fish {
//     swim();
//     layEggs();
// }

// function getSmallPet(): Fish | Bird {
//     return undefined
// }

// let pet = getSmallPet();
// pet.layEggs(); // okay
// pet.swim();    // errors

/* 类型别名 */
// type Name = string;
// type NameResolver = () => string;
// type NameOrResolver = Name | NameResolver;
// function getName(n: NameOrResolver): Name {
//     if (typeof n === "string") {
//         return n;
//     } else {
//         return n();
//     }
// }

// type Container<T> = { value: T };

// type Tree<T> = {
//     value: T;
//     left: Tree<T>;
//     right: Tree<T>;
// };

/* 接口 vs. 类型别名 */
/* 
接口创建了一个新的名字，可以在其它任何地方使用；
接口可以被继承和实现，别名不能；
如果你无法通过接口来描述一个类型并且需要使用联合类型或交叉类型，这时通常会使用类型别名
*/

/* 给联合类型起别名 */
type Easing = "ease-in" | "ease-out" | "ease-in-out";
